package com.teach.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.teach.commons.Id;
import com.teach.dto.ShopsSearch;
import com.teach.entity.ShopType;
import com.teach.entity.Shops;
import com.teach.entity.UserInfo;
import com.teach.exception.CodeException;
import com.teach.service.FileService;
import com.teach.service.ShopsService;
import com.teach.service.UserService;

/**
 * <pre>
 * 商铺服务基于MongoDB实现
 * 创建时间 ：	2019年12月10日 下午2:51:54
 * 当前版本 ：	V1.0
 * Copyright © 1998 - 2019 jlzhou.top. All Rights Reserved
 * </pre>
 * 
 * @author J.L.Zhou
 *
 */
@Service
public class ShopsServiceImpl implements ShopsService {

	@Autowired
	private MongoTemplate template;

	@Autowired
	private Id id;

	@Autowired
	private FileService fileService;
	
	@Autowired
	private UserService userService;

	@Override
	public void delete(Long id) {
		template.findAndRemove(Query.query(Criteria.where("id").is(id)), Shops.class);
	}

	@Override
	public Shops get(Long id) {
		return template.findOne(Query.query(Criteria.where("id").is(id)), Shops.class);
	}

	@Override
	public void modifyPass(Shops shops) {
		Shops oldShops = get(shops.getId());
		oldShops.setShopStatus(shops.getShopStatus());
		oldShops.setShopPassTime(new Date());//审核时间
		oldShops.setShopPassUserName(shops.getShopPassUserName());
		if(shops.getShopStatus()==2) {//通过
			UserInfo user = new UserInfo();
			user.setUserName(oldShops.getUserName());
			user.setRoleId(ShopType.values()[oldShops.getShopTypeId()].getRoleId());
			userService.modify(user);
		}
		
		template.save(oldShops);
	}

	@Override
	public void add(Shops shops, Double lng, Double lat, MultipartFile[] imgs, MultipartFile[] files) {
		if (StringUtils.isEmpty(shops.getUserName())) {
			throw new CodeException(70);
		}
		if (getByUserName(shops.getUserName()) != null) {
			throw new CodeException(71);
		}
		shops.setId(id.nextId());
		shops.setPoint(new Point(lng, lat));
		shops.setShopCreateTime(new Date());
		shops.setShopStatus(0);
		if (imgs == null || imgs.length == 0) {
			shops.setImg(new String[] {});
		} else {
			List<String> as = new ArrayList<>();
			for (int i = 0; i < imgs.length; i++) {
				if(!imgs[i].isEmpty()) {
					as.add( fileService.saveImage(imgs[i]));
				}
			}
			shops.setImg(as.toArray(new String[0]));
		}

		if (files == null || files.length == 0) {
			shops.setCertificates(new String[] {});
		} else {
			String[] as = new String[files.length];
			for (int i = 0; i < files.length; i++) {
				if (!files[i].isEmpty()) {
					as[i] = fileService.save(files[i],true);
				}
			}
			shops.setCertificates(as);
		}

		template.insert(shops);
	}

	@Override
	public void modify(Shops shops, Double lng, Double lat, int[] deleteImgs, MultipartFile[] imgs,
			MultipartFile[] files) {
		Shops oldShops = get(shops.getId());
		if (!StringUtils.isEmpty(shops.getShopMemo())) {
			oldShops.setShopMemo(shops.getShopMemo());
		}
		if (!StringUtils.isEmpty(shops.getShopName())) {
			oldShops.setShopName(shops.getShopName());
		}
		if (lng != null && lat != null) {
			oldShops.setPoint(new Point(lng, lat));
		}
		List<String> list = new ArrayList<>();
		Collections.addAll(list, oldShops.getImg());
		if (deleteImgs != null && deleteImgs.length > 0) {
			List<String> dels = new ArrayList<>();
			for (int index : deleteImgs) {
				dels.add(list.get(index));
			}
			list.removeAll(dels);
		}
		if (imgs != null && imgs.length > 0) {
			for (MultipartFile img : imgs) {
				list.add(fileService.saveImage(img));
			}
		}
		oldShops.setImg(list.toArray(new String[0]));

		if (files != null && files.length > 0) {
			for (int i = 0; i < files.length; i++) {
				if (!files[i].isEmpty()) {
					oldShops.getCertificates()[i]=fileService.save(files[0], true);
				}
			}
		}

		template.save(oldShops);
	}

	@Override
	public ShopType getType(Integer shopTypeId) {
		return ShopType.values()[shopTypeId];
	}

	private static List<ShopType> list = new ArrayList<>(ShopType.values().length);
	static {
		Collections.addAll(list, ShopType.values());
	}

	@Override
	public List<ShopType> listType() {
		return list;
	}

	@Override
	public Shops getByUserName(String userName) {
		Query query = Query.query(Criteria.where("userName").is(userName));
		return template.findOne(query, Shops.class);
	}

	private Query getQuery(ShopsSearch search) {
		Query q = new Query();
		if (!StringUtils.isEmpty(search.getKey())) {
			Pattern pattern = Pattern.compile("^.*" + search.getKey() + ".*$", Pattern.CASE_INSENSITIVE);
			Criteria c = new Criteria();
			c.orOperator(
					Criteria.where("userName").regex(pattern),
					Criteria.where("shopName").regex(pattern)
					);
			q.addCriteria(c);
		}
		if (search.getShopTypeId() != null) {
			q.addCriteria(Criteria.where("shopTypeId").is(search.getShopTypeId()));
		}
		if (search.getShopStatus() != null) {
			q.addCriteria(Criteria.where("shopStatus").is(search.getShopStatus()));
		}
		if (search.getLat() != null && search.getLng() != null) {
			if (search.getR() != null) {
				q.addCriteria(Criteria.where("point")
						.within(new Circle(new Point(search.getLng(), search.getLat()), search.getR())));
			} else {
				q.addCriteria(Criteria.where("point").near(new Point(search.getLng(), search.getLat())));
			}
		}
		return q;
	}

	@Override
	public Page<Shops> page(ShopsSearch search) {
		Pageable p = new MyPageable(search.getCurrent(), search.getRowMax());
		Query q = getQuery(search);
		q.with(p);
		Page<Shops> page = new PageImpl<>(template.find(q, Shops.class), p, template.count(q, Shops.class));
		
		List<Shops> list = page.getContent();
		for(Shops s : list) {
			s.setCertificates(null);
		}
		
		return  page;
	}

	@Override
	public List<Shops> list(ShopsSearch search) {
		Query q = getQuery(search);
		q.limit(search.getRowMax());
//		q.with(p);
		List<Shops> list = template.find(q, Shops.class);
		for(Shops s : list) {
			s.setCertificates(null);
		}
		return list;
	}

	public static class MyPageable implements Pageable {

		private int pageNumber;
		private int pageSize;

		/**
		 * @param pageNumber
		 * @param pageSize
		 */
		public MyPageable(int pageNumber, int pageSize) {
			super();
			this.pageNumber = pageNumber;
			this.pageSize = pageSize;
		}

		@Override
		public int getPageNumber() {
			return pageNumber;
		}

		@Override
		public int getPageSize() {
			return pageSize;
		}

		@Override
		public long getOffset() {
			return (pageNumber - 1) * pageSize;
		}

		@Override
		public Sort getSort() {
			return Sort.by(Direction.DESC, "_id");
		}

		@Override
		public Pageable next() {
			return null;
		}

		@Override
		public Pageable previousOrFirst() {
			return null;
		}

		@Override
		public Pageable first() {
			return null;
		}

		@Override
		public boolean hasPrevious() {
			return pageNumber > 1;
		}

	}

}
